/**
 * <b>项目名：</b>monitor<br/>
 * <b>包名：</b>org.monitor.main<br/>
 * <b>文件名：</b>Server.java<br/>
 * <b>版本信息：</b> @version 1.0.0<br/>
 * <b>日期：</b>2013-6-8-下午6:11:20<br/>
 * <b>Copyright (c)</b> 2013魅族公司-版权所有<br/>
 *
 */

package org.monitor.main;

import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.monitor.beans.Client;
import org.monitor.beans.RequestParam;
import org.monitor.common.Common;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.Request;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.AbstractHandler;
import org.mortbay.jetty.handler.DefaultHandler;
import org.mortbay.jetty.handler.HandlerList;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * <b>类名称：</b>MServer<br/>
 * <b>类描述：</b>
 * 
 * <pre>
 </pre>
 * 
 * <br/>
 * <b>创建人：</b>张军强<br/>
 * <b>修改人：</b>张军强<br/>
 * <b>修改时间：</b>2013-6-8 下午6:11:20<br/>
 * <b>修改备注：</b><br/>
 * 
 * @version 1.0.0<br/>
 */

public class MServer implements IService {

	private static String serverKey = "-1";

	private  static final String COMMON_CONFIG = "COMMON";
	private static HashMap<Long, String> clientKeys = new HashMap<Long, String>();

	private static Logger logger = Logger.getLogger(MServer.class);
	
	
    private static ConcurrentHashMap<String, Long> mailLogger=new ConcurrentHashMap<String, Long>();
    
    
    private static ConcurrentHashMap<String, HashMap<String, Object>> clientMonitor=new ConcurrentHashMap<String,HashMap<String, Object>>();
	
	
//	private static 
	
	
	

	private static MServer _instance = new MServer();

	private static ConcurrentHashMap<String, Object> clientMap = new ConcurrentHashMap<String, Object>();
	
	private static ConcurrentHashMap<String, Map> clientConfig=new ConcurrentHashMap<String, Map>();

	private static boolean isRunning = false;

	private static Properties conf;

	private MServer() {

	}

	public static MServer getInstance() {
		return _instance;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.monitor.main.IService#startService(int)
	 */

	public void startService(Properties conf) {
		// TODO Auto-generated method stub

		if (!isRunning) {

			serverKey = conf.get("securityKey").toString();
			this.conf = conf;
			Server server = new Server(Integer.valueOf(conf.get("server.port").toString()));
			HandlerList handlers = new HandlerList();
			handlers.setHandlers(new Handler[] { new ServerHandler(), new DefaultHandler() });
			server.setHandler(handlers);
			try {
				server.start();
				// server.join();
				isRunning = true;
				logger.info("服务成功启动");
				
				
				
				{
					
					//初始化监控列表
					String client=Common.getFile(Main.confPath+"/conf/clients");
					HashSet<String> hosts=new HashSet<String>();
					String[] clients = client.split("\\r|\\n");
					clientMonitor.clear();
					for (int i = 0; i < clients.length; i++) {
						if(!clients[i].equals("")){
							hosts.add(clients[i]);
							HashMap<String, Object> map=new HashMap<String, Object>();
							map.put("cdate", new Date().getTime());
							clientMonitor.put(clients[i], map);
						}
					}

				}
				
				
				new Thread(){
					public synchronized void run() {
						
						try {
							while(true){
								
								
								  long curTime=new Date().getTime();
								
									 Iterator<String> it = clientMonitor.keySet().iterator();
									 while(it.hasNext()){
										 String host= it.next();
										 Map map= clientMonitor.get(host);
										 Long cdate= Long.valueOf( map.get("cdate").toString());
										 if(cdate+1000*60*10<curTime){
											 map.put("cdate", curTime);
											 MailFactory.send(Main.getConfig().getProperty("server.mail"), "监控系统", "监控系统", host+"\r\n"+"监控没启动");
										 }
									 }
									 
									Thread.sleep(1000*60);
							
								
							}
						}catch (Exception e) {
							// TODO: handle exception
						}
						
					};
					
				}.start();
				
			} catch (Exception e) {
				logger.error("服务启动出错");
			}
		}

	}
	
	
	


	public static class ServerHandler extends AbstractHandler {
		
		public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException {

			response.setContentType("text/html;charset=UTF-8"); 
			String action = request.getParameter("action") == null ? "" : request.getParameter("action");
			request.setCharacterEncoding("utf-8");

			if (target.startsWith("/web/service")) {// 网页调用

				if (action.equalsIgnoreCase("execCmd")) {
					execCmd(request, response);
				} else if (action.equalsIgnoreCase("getData")) {
					getData(request, response);
				} else if(action.equalsIgnoreCase("getDevices")){
					getDevices(request, response);
				} else if(action.equalsIgnoreCase("saveDevices")){
					saveDevices(request, response);
				}else if(action.equalsIgnoreCase("loadSetting")){
					loadSetting(request, response);
				}else if(action.equalsIgnoreCase("saveSetting")){
					saveSetting(request, response);
				}

			} else if(target.startsWith("/web/js/")){
				
			  String filename=target.replace("/web/js/", "");
			  String html=   Common.getFile(	MServer.class.getResourceAsStream("/org/monitor/resource/js/"+filename));
			    response.getWriter().write(html);
			    
				
			} else if(target.startsWith("/web/")){
				
				  String html=   Common.getFile(	MServer.class.getResourceAsStream("/org/monitor/resource/index.html"));
				    response.getWriter().write(html);
				    
					
			} else { // 客户端调用

				if (Common.checkSign(request, response)) {

					if (action.equalsIgnoreCase("postData")) {
						postData(request, response);
					} else if (action.equalsIgnoreCase("registerService")) {
						registerService(request, response);
					} else {
						response.getWriter().write("undefined service");
					}
				} else {

					logger.info("受攻击了！");
				}

			}

			response.getWriter().flush();
			response.setStatus(HttpServletResponse.SC_OK);
			((Request) request).setHandled(true);

		}
	}

	/**
	 * <b>创建人：</b>张军强<br/>
	 * main<br/>
	 * <b>方法描述：</b> <br/>
	 * 
	 * @param args
	 *            void
	 * @exception
	 * @since 1.0.0
	 */

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
	
	
	
		 
		 
		 
		 /**
		 * <b>创建人：</b>张军强<br/>
		 * saveDevices<br/>
		 *<b>方法描述：</b> <br/>
		 * @param request
		 * @param response 
		 * void
		 * @exception 
		 * @since  1.0.0
		 */
		
	public synchronized static void saveDevices(HttpServletRequest request, HttpServletResponse response) {
		
		try {
			String client=Common.getReuestParam(request, "clients");
			HashSet<String> hosts=new HashSet<String>();
			String[] clients = client.split("\\r|\\n");
			clientMonitor.clear();
			for (int i = 0; i < clients.length; i++) {
				if(!clients[i].equals("")){
					hosts.add(clients[i]);
					HashMap<String, Object> map=new HashMap<String, Object>();
					map.put("cdate", new Date().getTime());
					clientMonitor.put(clients[i], map);
				}
			}
			StringBuffer buf=new StringBuffer();
			Iterator<String> it = hosts.iterator();
			while(it.hasNext()){
				buf.append(it.next()+"\r\n");
			}
			Common.writeFile(Main.confPath+"/conf/clients",buf.toString());
			response.getWriter().write("保存成功！");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			
			logger.debug(e.getMessage());
			e.printStackTrace();
		}
		
	}
	
	
	public synchronized static void loadSetting(HttpServletRequest request, HttpServletResponse response) {
		
		try {
		    String host= Common.getReuestParam(request, "host");
		    host=host.replaceAll(":\\d+", "");
			String clients= Common.getFile( Main.confPath+"/conf/"+host+".js");
			
			response.getWriter().write(clients);
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	
	
public synchronized static void saveSetting(HttpServletRequest request, HttpServletResponse response) {
	
	try {
		String setting=Common.getReuestParam(request, "setting");
		setting=URLDecoder.decode(setting, "UTF-8"); 
		 String host= Common.getReuestParam(request, "host"); 
		 host=host.replaceAll(":\\d+", "");
		 try {
			 JSON.parse(setting); 
		Common.writeFile(Main.confPath+"/conf/"+host+".js",setting);
		response.getWriter().write("保存成功！");
		 }catch (Exception e) {
			 response.getWriter().write("保存失败！");
		}
	} catch (IOException e) {
		// TODO Auto-generated catch block
		
		logger.debug(e.getMessage());
		e.printStackTrace();
	}
	
}
	

		/**
		 * <b>创建人：</b>张军强<br/>
		 * getDevices<br/>
		 *<b>方法描述：</b> <br/>
		 * @param request
		 * @param response 
		 * void
		 * @exception 
		 * @since  1.0.0
		 */
		
	public synchronized static void getDevices(HttpServletRequest request, HttpServletResponse response) {
	
		try {
			String clients= Common.getFile( Main.confPath+"/conf/clients");
			
			response.getWriter().write(clients);
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	public static <T> T getClientConf(String host,String key){
	   Map map=(Map)clientMap.get(host);
	   return (T) map.get(key);
	}

	
		 
		 /**
		 * <b>创建人：</b>张军强<br/>
		 * execCmd<br/>
		 *<b>方法描述：</b> <br/>
		 * @param request
		 * @param response 
		 * void
		 * @throws IOException 
		 * @exception 
		 * @since  1.0.0
		 */
		
	public static void execCmd(HttpServletRequest request, HttpServletResponse response) throws IOException {
		
		JSONObject json= (JSONObject) JSONObject.parse( request.getParameter("param")==null?"{}":request.getParameter("param").toString());
		
		
	    String host= json.get("host").toString();
	    
	    String registerKey= getClientConf(host, "registerKey");
	    
	    RequestParam param= Common.makeSign(registerKey);
	    
	    param.setAction("execCmd");
	    
	    param.getParam().put("cmd", json.get("cmd"));
	    param.getParam().put("termIp", request.getRemoteHost());
	    
	    
	    
	    response.getWriter().write(  Common.postData("http://"+host, param.getParamsForClent()));
	    
	    
		
		
		
	}
	
	
	public static String getInfo(){
		
		
		HashMap<String,Object> map=new  HashMap<String,Object>();
		map.put("name", "TSTRETEWRTWQETRQWETRQWR");
		
		return JSON.toJSONString(map);
	}
	
	
	public static String getDeviceList(){
		ArrayList<HashMap<String, String>> list=new ArrayList<HashMap<String, String>>();
		
		 Iterator<String> it = clientMap.keySet().iterator();
		 while(it.hasNext()){
			
			 HashMap<String, String> tmp=new HashMap<String, String>();
			 String key=it.next();
			 tmp.put("device", key);
			 HashMap<String,Object> map=(HashMap)clientMap.get(key);
			 if( Long.valueOf( map.get("cdate").toString())>new Date().getTime()-1000*60*1){
				 list.add(tmp);
			 }
			 
		 }
		 return JSON.toJSONString(list);
	}
	

	public static void getData(HttpServletRequest request, HttpServletResponse response) throws IOException {
		
		
		String action= Common.getReuestParam(request, "action");
		
		String result="";
		
		
		if(action.equalsIgnoreCase("getDeviceList")){
			
			result=getDeviceList();
			
		} else	if(action.equalsIgnoreCase("getInfo")){
			
			result=getInfo();
			
		}
		
		
		response.getWriter().write(result);
	}

	/**
	 * <b>创建人：</b>张军强<br/>
	 * registerService<br/>
	 * <b>方法描述：</b> <br/>
	 * 
	 * @param request
	 * @param response
	 *            void
	 * @exception
	 * @since 1.0.0
	 */

	public static void registerService(HttpServletRequest request, HttpServletResponse response) {
		HashMap<String, String> map = new HashMap<String, String>();
		JSONObject param = JSONObject.parseObject(request.getParameter("param"), JSONObject.class);
		String clientMD5 = (String) param.get("md5");
		String registerKey = (String) param.get("rand");
		String serverMD5 = Common.md5(conf.getProperty("securityKey") + registerKey); 
		if (serverMD5.equals(clientMD5)) {
			String ip = request.getRemoteHost();
			
			int port = param.getIntValue("port");
			Client clientHost = new Client();
			clientHost.setIp(ip);
			clientHost.setPort(port);
			HashMap<String, Object> clientData=new HashMap<String, Object>();
			clientData.put("registerKey", registerKey);
			clientData.put("cdate", new Date().getTime());
			clientMap.put(clientHost.toString(), clientData);
			
			 HashMap<String, Object> cm = clientMonitor.get(ip);
			 if(cm!=null){
				 cm.put("cdate", new Date().getTime());
			 }
			
			//System.out.println(clientMap);
			
			//logger.debug(clientMap);
			 
			 if(Main.isDebug()){
				 logger.debug(clientMap); 
			 }

			try {
				
				String priPath=Main.confPath+"/conf/"+ip+".js";

				String commonJson=Common.getFile(Main.confPath+"/conf/common.js");
				
			
				File f=new File(priPath);
				if(!f.exists()){
					f.createNewFile();
					Common.writeFile(priPath, commonJson);
				}
				
				
				
				String priJson=Common.getFile(priPath);
				
				
			
				
				JSONObject commonCommand = JSONObject.parseObject(commonJson);
				
				HashMap<String, Object> mapc=new HashMap<String, Object>();
				for (String category : commonCommand.keySet()) {
					JSONArray jarray = commonCommand.getJSONArray(category);
					for (int i = 0; i < jarray.size(); i++) {
							JSONObject obj = (JSONObject) jarray.get(i);
							
							mapc.put(obj.getString("key"), obj);
							

					}
				}
				
				
	
				clientConfig.put(COMMON_CONFIG,mapc );
				
				JSONObject privateCommand = JSONObject.parseObject(priJson);
				HashMap<String, Object> mapp=new HashMap<String, Object>();
				for (String category : privateCommand.keySet()) {
					JSONArray jarray = privateCommand.getJSONArray(category);
					for (int i = 0; i < jarray.size(); i++) {
							JSONObject obj = (JSONObject) jarray.get(i);
							
							mapp.put(obj.getString("key"), obj);
							

					}
				}
				
				clientConfig.put(ip,mapp );
				
				HashMap<String, Object> resultMap=new HashMap<String, Object>();
				resultMap.put("common", commonCommand);
				resultMap.put("private", privateCommand);
				
				response.getWriter().write(JSON.toJSONString(resultMap));
				response.flushBuffer();

				// System.out.println( Common.getFile( Common.getProjectPath()+
				// java.io.File.separator+"common.js"));
			} catch (Exception e) {
				e.printStackTrace();
				logger.error("registerService:\t" +e.getMessage());
				// TODO: handle exception
			}
		}

	}

	/**
	 * <b>创建人：</b>张军强<br/>
	 * postData<br/>
	 * <b>方法描述：</b> <br/>
	 * 
	 * @param request
	 * @param response
	 *            void
	 * @throws IOException 
	 * @exception
	 * @since 1.0.0
	 */
	// TODO 与Common中间的重复了??? 没有重复，中间应该调用common的postData方法，类似execCmd这个方法的处理方式
	public synchronized  static void postData(HttpServletRequest request, HttpServletResponse response) throws IOException {
		
		
		String data=request.getParameter("param");
		
		try {
			
			String host= request.getRemoteHost();
		
		
		
		 String section= Common.getReuestParam(request, "section");
		 Map client =null; 
		 if(section.equalsIgnoreCase("common")){
			 client= clientConfig.get(COMMON_CONFIG);
		 } else {
			 client= clientConfig.get(host);
		 }
		
		 String key= Common.getReuestParam(request, "key");

		 Map cmdMap=(Map)client.get(key);

		 
		 String js=Common.getFile(Main.confPath+"/conf/util.js");
		 
		 
		 if(Main.isDebug()){
			 
			 logger.debug("MServer:\t" + host+"\t"+ request.getParameter("param"));

		 
		 }
		 //System.out.println(Common.getReuestParam(request, "data").toString());
		 
		 
		 Object isPass = Common.execJsFunc(js, cmdMap.get("assertfunction").toString(),  new Object[]{Common.getReuestParam(request, "data").toString(), cmdMap.get("assertvalue").toString()});
		
		 
		 String email=cmdMap.get("email").toString();
		 
		 String desc=cmdMap.get("desc").toString();
		 
		 boolean alarm =cmdMap.get("alarm")==null?true:((Boolean)cmdMap.get("alarm"));
		 
		 
		
		
		 
		 if((Boolean)isPass){ 
			 String mailKey=host+":"+key;
			 
			 Long mailTime = mailLogger.get(mailKey)==null?0:mailLogger.get(mailKey);
			 
			 long curTime= new Date().getTime();
			 long interval= Main.getConfig().get("alarm.interval")==null?10: Long.valueOf( Main.getConfig().get("alarm.interval").toString());
			 if(mailTime+ interval*1000*60*120 <curTime ){//两小时发一次
				 if(alarm) {
					 MailFactory.getInstance().send(email, "监控系统","监控系统" , host+"\r\n"+ desc+"出错！"); 
				 	mailLogger.put(mailKey, curTime);
				 }
			 }
			 
			
		 }
		 
		
		 
		
		}catch (Exception e) {
			logger.error("postData:\t"+ data);
		}
		 
		
		

	}
	
	

}
